#include "stdafx.h"

int32_t wmain(int32_t nArgc, const wchar_t* pArgv[]) {
	shared_ptr<Interface> Intf = make_shared<Interface>(false, VerbosityLevel::Surface);
	shared_ptr<ApiTable> DynamicApis = make_shared<ApiTable>(Intf);

	if (nArgc < 3) {
		Intf->Log("... usage: %ws <PID> <DLL path> <Optional log file path>\r\n", pArgv[0]);
	}
	else {
		uint32_t dwPid = _wtoi(pArgv[1]);
		wstring DllPath = pArgv[2];
		wstring LogPath;

		if (nArgc == 4) {
			LogPath = pArgv[3];
		}

		try {
			Process Ps(Intf, DynamicApis, dwPid, L"");
			bool bValidTarget = false;
#ifdef _WIN64
			if (!Ps.IsWow64()) {
				bValidTarget = true;
			}
#else
			if (Ps.IsWow64()) {
				bValidTarget = true;
			}
#endif
			if (bValidTarget) {
				if (Ps.IsAppContainer()) {
					Intf->Log(VerbosityLevel::Detail, "... target PID %d is an AppContainer. Adding ACL for SID on log at %ws\r\n", dwPid, LogPath.c_str());
					if (Ps.GetAppContainerInfo() != nullptr) {
						if (GrantNamedObjectAccess(Ps.GetAppContainerInfo()->TokenAppContainer, (wchar_t*)LogPath.c_str(), SE_FILE_OBJECT, GENERIC_ALL)) {
							Intf->Log(VerbosityLevel::Detail, "... successfully granted access to %ws to AppContainer\r\n", LogPath.c_str());
						}
					}
					else {
						Intf->Log(VerbosityLevel::Detail, "... no AppContainer info present\r\n");
					}
				}
				else {
					Intf->Log(VerbosityLevel::Detail, "... target PID %d is not an AppContainer\r\n", dwPid);
				}

				if (Ps.InjectDLL(DllPath)) {
					Intf->Log("... successfully injected %ws into %d\r\n", DllPath.c_str(), dwPid);
				}
				else {
					Intf->Log("... failed to inject %ws into %d\r\n", DllPath.c_str(), dwPid);
				}
			}
			else {
				Intf->Log("... target PID %d has a mismatching architecture with this tool (use the 32 or 64-bit version accordingly)\r\n", dwPid);
			}
		}
		catch (int32_t nError) {
			Intf->Log("... failed to initialize class object for PID %d\r\n", dwPid);
		}
	}

	return 0;
}